package com.apps.shelper;


import com.apps.sexctption.DataException;
import com.apps.sexctption.NullException;
import com.apps.sutils.StringUtils;
import com.apps.sutils.ValidatorUtils;
import com.apps.sannotation.constraints.*;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.util.regex.Pattern;

/**
 * 验证工具类
 */
@Slf4j
public class ValidationHepler {


    /**
     * 验证某个对象是否为空
     * @param object
     */
    public static boolean validNullByObject(Object object)
    {

        if(null==object)
            return false;
        if(object.getClass().isAssignableFrom(String.class) && StringUtils.isEmpty(object.toString()))
            return false;
        return true;
    }

    /**
     * 执行NoNull的验证规则
     * @param object
     */
    public static void validNoNullAnnotation(String fieldname, Object object, NoNull noNull)
    {
        //非空验证
        if(!validNullByObject(object)) {
            throw new NullException(fieldname + noNull.errMsg());
        }
    }

    /**
     * 执行邮箱验证
     * @param object
     * @return
     */
    public static void validEmailAnnotation(String fieldname,Object object, Email email)
    {
        //非空验证
        if(!ValidationHepler.validNullByObject(object))
           return;

        if(!object.getClass().isAssignableFrom(String.class))
            throw new DataException(fieldname+"不是一个字符串");
        //验证邮箱是否合法
        if(!ValidatorUtils.isEmail(object.toString()))
            throw new DataException(object+email.errMsg());
    }

    /**
     * 执行手机号验证
     * @param object
     * @return
     */
    public static void validMobileAnnotation(String fieldname, Object object, Mobile mobile)
    {
        //非空验证
        if(!ValidationHepler.validNullByObject(object))
            return;

        if(!object.getClass().isAssignableFrom(String.class))
            throw new DataException(fieldname+"不是一个字符串");
        //验证手机号是否合法
        if(!ValidatorUtils.isMobile(object.toString()))
            throw new DataException(object+mobile.errMsg());
    }

    /**
     * 验证字符串长度是否合法
     * @param fieldname
     * @param object
     */
    public static void validStrLenAnnotation(String fieldname, Object object, StrLen len)
    {
        //非空验证
        if(!ValidationHepler.validNullByObject(object))
            return;

        if(!object.getClass().isAssignableFrom(String.class))
            throw new DataException(fieldname+"目标不是一个字符串");

        String value=object.toString();
        //验证字符串长度是否合法
        if(value.length() < len.min() || value.length() > len.max())
            throw new DataException(object+len.errMsg());
    }

    /**
     * 验证字符串长度是否低于允许范围
     * @param fieldname
     * @param object
     * @param minLen
     */
    public static void validStrMinLenAnnotation(String fieldname, Object object, StrMinLen minLen)
    {
        //非空验证
        if(!ValidationHepler.validNullByObject(object))
            return;

        if(!object.getClass().isAssignableFrom(String.class))
            throw new DataException(fieldname+"目标不是一个字符串");

        String value=object.toString();
        //验证字符串长度是否合法
        if(value.length() < minLen.min())
            throw new DataException(object+minLen.errMsg());
    }

    /**
     * 验证字符串长度是否大于允许范围
     * @param fieldname
     * @param object
     * @param maxLen
     */
    public static void validStrMaxLenAnnotation(String fieldname, Object object, StrMaxLen maxLen)
    {
        //非空验证
        if(!ValidationHepler.validNullByObject(object))
            return;

        if(!object.getClass().isAssignableFrom(String.class))
            throw new DataException(fieldname+"目标不是一个字符串");

        String value=object.toString();
        //验证字符串长度是否合法
        if(value.length() > maxLen.max())
            throw new DataException(object+maxLen.errMsg());
    }

    /**
     * 验证字符串的值是否在允许范围
     * @param fieldname
     * @param object
     * @param strRange
     */
    public static void validStrRangeAnnotation(String fieldname, Object object, StrRange strRange)
    {
        //非空验证
        if(!ValidationHepler.validNullByObject(object))
            return;

        if(!object.getClass().isAssignableFrom(String.class))
            throw new DataException(fieldname+"目标不是一个字符串");

        //验证字符串长度是否合法
        int count=0;
        for(String s:strRange.value())
            if(object.toString().equals(s)) {
                count++;
                break;
            }
        if(count <= 0)
           throw new DataException(object+strRange.errMsg());
    }

    /**
     * 验证字符串是否跟Enum匹配
     * @param fieldname
     * @param object
     * @param strEnums
     */
    @SneakyThrows
    public static void validStrEnumsAnnotation(String fieldname, Object object, StrEnums strEnums)
    {
        //非空验证
        if(!ValidationHepler.validNullByObject(object))
            return;

        if(!object.getClass().isAssignableFrom(String.class))
            throw new DataException(fieldname+"目标不是一个字符串");
        Object[] values= (Object[]) strEnums.enums().getMethod("values").invoke(strEnums.enums());
        //验证字符串长度是否合法
        int count=0;
        for(Object e: values)
        {
            if(e.toString().equals(object.toString())) {
                count++;
                break;
            }
        }

        if(count <= 0)
            throw new DataException(object+strEnums.errMsg());
    }

    /**
     * 正则匹配验证
     * @param fieldname
     * @param object
     * @param strPattern
     */
    @SneakyThrows
    public static void validStrPattenAnnotation(String fieldname, Object object, StrPattern strPattern)
    {
        //非空验证
        if(!ValidationHepler.validNullByObject(object))
            return;

        if(!object.getClass().isAssignableFrom(String.class))
            throw new DataException(fieldname+"目标不是一个字符串");

        if(!Pattern.matches(strPattern.matches(),object.toString()))
            throw new DataException(object+strPattern.errMsg());
    }
    /**
     * 验证字符串必须是数字
     * @param fieldname
     * @param object
     * @param strIsNumber
     */
    @SneakyThrows
    public static void validStrIsNumberAnnotation(String fieldname, Object object, StrIsNumber strIsNumber)
    {
        //非空验证
        if(!ValidationHepler.validNullByObject(object))
            return;

        if(!object.getClass().isAssignableFrom(String.class))
            throw new DataException(fieldname+"目标不是一个字符串");

        if(!StringUtils.isInteger(object.toString()))
            throw new DataException(object+strIsNumber.errMsg());
    }

    /**
     * 验证数字是否合法
     * @param fieldname
     * @param object
     * @param numRange
     */
    public static void validNumRangeAnnotation(String fieldname, Object object, NumRange numRange)
    {
        //非空验证
        if(!ValidationHepler.validNullByObject(object))
            return;

        if(object.getClass().isAssignableFrom(Integer.class))
        {
            //验证整数范围是否合法
            Integer value = (Integer) object;
            if (value.intValue() < numRange.min() || value.intValue() > numRange.max())
                throw new DataException(object+numRange.errMsg());
        }
        else if(object.getClass().isAssignableFrom(Float.class))
        {
            //验证整数范围是否合法
            Float value = (Float) object;
            if (value.intValue() < numRange.min() || value.intValue() > numRange.max())
                throw new DataException(object+numRange.errMsg());
        }
        else if(object.getClass().isAssignableFrom(Double.class))
        {
            //验证整数范围是否合法
            Double value = (Double) object;
            if (value.intValue() < numRange.min() || value.intValue() > numRange.max())
                throw new DataException(object+numRange.errMsg());
        }
        else if(object.getClass().isAssignableFrom(Long.class))
        {
            //验证整数范围是否合法
            Long value = (Long) object;
            if (value.intValue() < numRange.min() || value.intValue() > numRange.max())
                throw new DataException(object+numRange.errMsg());
        }
        //如果是大数类型
        else if(object.getClass().isAssignableFrom(BigDecimal.class))
        {
            BigDecimal value= (BigDecimal) object;
            if (value.compareTo(new BigDecimal(numRange.min())) == -1 || value.compareTo(new BigDecimal(numRange.max())) == 1)
                throw new DataException(object+numRange.errMsg());
        }else
            throw new DataException(fieldname+"不是一个数字");
    }

    /**
     * 验证数字范围
     * @param fieldname
     * @param object
     * @param numLimits
     */
    public static void validNumLimitsAnnotation(String fieldname, Object object, NumLimits numLimits)
    {
        //非空验证
        if(!ValidationHepler.validNullByObject(object))
            return;

        if(object.getClass().isAssignableFrom(Integer.class) ||
           object.getClass().isAssignableFrom(Float.class) ||
           object.getClass().isAssignableFrom(Double.class) ||
           object.getClass().isAssignableFrom(Long.class))
        {
            //验证范围是否合法
            int count=0;
            for(float item:numLimits.ranges())
                if(object.equals(item))
                    count++;
            if(count <= 0)
               throw new DataException(object+numLimits.errMsg());
        }else if(object.getClass().isAssignableFrom(BigDecimal.class))
        {
            BigDecimal value= (BigDecimal) object;
            int count=0;
            for(float item:numLimits.ranges())
                if(value.compareTo(new BigDecimal(item)) == 1)
                    count++;
            if(count <= 0)
                throw new DataException(object+numLimits.errMsg());
        }
         else
            throw new DataException(fieldname+"不是一个数字");
    }
    /**
     * 验证数字最小范围
     * @param fieldname
     * @param object
     * @param nummin
     */
    public static void validNumMinAnnotation(String fieldname, Object object, NumMin nummin)
    {
        //非空验证
        if(!ValidationHepler.validNullByObject(object))
            return;

        if(object.getClass().isAssignableFrom(Integer.class))
        {
            //验证整数范围是否合法
            Integer value = (Integer) object;
            if (value.intValue() <= nummin.min())
                throw new DataException(object+nummin.errMsg());
        }
        else if(object.getClass().isAssignableFrom(Float.class))
        {
            //验证整数范围是否合法
            Float value = (Float) object;
            if (value.intValue() <= nummin.min())
                throw new DataException(object+nummin.errMsg());
        }
        else if(object.getClass().isAssignableFrom(Double.class))
        {
            //验证整数范围是否合法
            Double value = (Double) object;
            if (value.intValue() <= nummin.min())
                throw new DataException(object+nummin.errMsg());
        }
        else if(object.getClass().isAssignableFrom(Long.class))
        {
            //验证整数范围是否合法
            Long value = (Long) object;
            if (value.intValue() <= nummin.min())
                throw new DataException(object+nummin.errMsg());
        }
        //如果是大数类型
        else if(object.getClass().isAssignableFrom(BigDecimal.class))
        {
            BigDecimal value= (BigDecimal) object;
            if (value.compareTo(new BigDecimal(nummin.min())) == -1 || value.compareTo(new BigDecimal(nummin.min())) == 0)
                throw new DataException(object+nummin.errMsg());
        }else
            throw new DataException(fieldname+"目标不是一个数字");
    }

    /**
     * 验证数字最大允许值
     * @param fieldname
     * @param object
     * @param nummax
     */
    public static void validNumMaxAnnotation(String fieldname, Object object, NumMax nummax)
    {
        //非空验证
        if(!ValidationHepler.validNullByObject(object))
            return;

        if(object.getClass().isAssignableFrom(Integer.class))
        {
            //验证整数范围是否合法
            Integer value = (Integer) object;
            if (value.intValue() <= nummax.max())
                throw new DataException(object+nummax.errMsg());
        }
        else if(object.getClass().isAssignableFrom(Float.class))
        {
            //验证整数范围是否合法
            Float value = (Float) object;
            if (value.intValue() <= nummax.max())
                throw new DataException(object+nummax.errMsg());
        }
        else if(object.getClass().isAssignableFrom(Double.class))
        {
            //验证整数范围是否合法
            Double value = (Double) object;
            if (value.intValue() <= nummax.max())
                throw new DataException(object+nummax.errMsg());
        }
        else if(object.getClass().isAssignableFrom(Long.class))
        {
            //验证整数范围是否合法
            Long value = (Long) object;
            if (value.intValue() <= nummax.max())
                throw new DataException(object+nummax.errMsg());
        }
        //如果是大数类型
        else if(object.getClass().isAssignableFrom(BigDecimal.class))
        {
            BigDecimal value= (BigDecimal) object;
            if (value.compareTo(new BigDecimal(nummax.max())) == -1 || value.compareTo(new BigDecimal(nummax.max())) == 0)
                throw new DataException(object+nummax.errMsg());
        }else
            throw new DataException(fieldname+"不是一个数字");
    }

    /**
     * 验证小数点位数是否过长
     * @param fieldname
     * @param object
     * @param decimalMaxLen
     */
    public static void validDecimalMaxLenAnnotation(String fieldname, Object object, DecimalMaxLen decimalMaxLen)
    {
        //非空验证
        if(!ValidationHepler.validNullByObject(object))
            return;

        if(object.getClass().isAssignableFrom(Integer.class))
            return;
        if(object.getClass().isAssignableFrom(Float.class) ||
           object.getClass().isAssignableFrom(Double.class) ||
           object.getClass().isAssignableFrom(Long.class)   ||
           object.getClass().isAssignableFrom(BigDecimal.class) ||
           object.getClass().isAssignableFrom(String.class))
        {
            //验证浮点数范围是否合法
            String[] s=object.toString().split("\\.");
            if(s.length<=1)
                return;
            if(s.length>2)
                throw new DataException(object+"有2个小数点");
            if(s[1].length() > decimalMaxLen.maxlen())
                throw new DataException(object+decimalMaxLen.errMsg());
        }else
            throw new DataException(fieldname+"不是一个数字");
    }

    public static void main(String... args)
    {
        String v="1234";
        String[] s=v.split("\\.");
        for(int i=0;i<s.length;i++)
            System.out.println(s[i]);

    }

}
